package cn.dm.example.threadPool;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 测试线程池中的线程交替执行
 */
@Slf4j
public class ThreadPoolExample5 {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
//        ExecutorService executorService = Executors.newCachedThreadPool();

        // 启动3个任务,每个任务执行的工作是打印10条数据
        for (int i = 0; i < 3; i++) {
            executorService.execute(new Task(i));
        }

        // 注:线程池关闭后,里面的线程还在继续运行
        executorService.shutdown();
        System.out.println("关闭线程池");

        // 关闭线程池后,再执行任务会报"RejectedExecutionException"异常
        // executorService.execute(new Task(10));

        while (!executorService.isTerminated()) {
            // 若是线程池的线程仍在运行,则休眠100ms
            Thread.sleep(100L);
        }
        System.out.println("线程池中的任务全部运行结束.");

        /**
         * 运行结果如下
         *
         * 关闭线程池
         * 11:54:54.500 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=1, i=0
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=1, i=1
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=1, i=2
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=1, i=3
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=1, i=4
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=1, i=5
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=1, i=6
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=1, i=7
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=1, i=8
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=1, i=9
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - thread 1 run end.
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=2, i=0
         * 11:54:54.500 [pool-1-thread-1] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=0, i=0
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=2, i=1
         * 11:54:54.504 [pool-1-thread-1] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=0, i=1
         * 11:54:54.504 [pool-1-thread-1] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=0, i=2
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=2, i=2
         * 11:54:54.504 [pool-1-thread-1] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=0, i=3
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=2, i=3
         * 11:54:54.504 [pool-1-thread-1] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=0, i=4
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=2, i=4
         * 11:54:54.504 [pool-1-thread-1] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=0, i=5
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=2, i=5
         * 11:54:54.504 [pool-1-thread-1] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=0, i=6
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=2, i=6
         * 11:54:54.504 [pool-1-thread-1] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=0, i=7
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=2, i=7
         * 11:54:54.504 [pool-1-thread-1] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=0, i=8
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=2, i=8
         * 11:54:54.504 [pool-1-thread-1] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=0, i=9
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - taskNum=2, i=9
         * 11:54:54.504 [pool-1-thread-1] INFO cn.dm.example.threadPool.ThreadPoolExample5 - thread 0 run end.
         * 11:54:54.504 [pool-1-thread-2] INFO cn.dm.example.threadPool.ThreadPoolExample5 - thread 2 run end.
         * 线程池中的任务全部运行结束.
         *
         * Process finished with exit code 0
         *
         *
         * 分析:"关闭线程池"这句话打印的很靠前,shutdown之后是线程池不接受新的线程任务,但已经在线程池中的线程(已开始或者未开始的)会保证该线程执行完毕
         * isTerminated()是判断线程池中的线程是否执行完毕
         */
    }


    private static class Task implements Runnable {
        private int taskNum; // 任务号

        public Task(int taskNum) {
            this.taskNum = taskNum;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                log.info("taskNum={}, i={}", taskNum, i);
            }
            log.info("thread {} run end.", taskNum);
        }
    }
}
